#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "os_api.h"
#include "debug.h"
#include "uart.h"


typedef struct{
    int port;   // 0:uart, 1:uart3, 2:uart4
    int len;
    UINT8 *data;
}uartParam;

static OSMsgQRef uartMsgQ = NULL;

#define _TASK_STACK_SIZE     1024*8
static void* _task_stack = NULL;
static OSTaskRef _task_ref = NULL;


void mainUartRecvCallback(UINT8 * recv_data, UINT32 recv_len)
{	
	uartParam uart_data = {0};
    OSA_STATUS osa_status;
    
    char *tempbuf = (char *)malloc(recv_len+1);
    memset(tempbuf, 0x0, recv_len+1);
    memcpy(tempbuf, (char *)recv_data, recv_len);
	
    LOG_PRINTF("%s[%d]: recv_len:%d, recv_data:%s\n", __FUNCTION__, __LINE__, recv_len, (char *)(tempbuf)); 
    uart_data.data = (UINT8 *)tempbuf;
    uart_data.len = recv_len;
    uart_data.port = 0;
	
    osa_status = OSAMsgQSend(uartMsgQ, sizeof(uartParam), (UINT8*)&uart_data, OSA_NO_SUSPEND);
    ASSERT(osa_status == OS_SUCCESS);
}

void uart3RecvCallback(UINT8 * recv_data, UINT32 recv_len)
{	
	uartParam uart_data = {0};
    OSA_STATUS osa_status;
    
    char *tempbuf = (char *)malloc(recv_len+1);
    memset(tempbuf, 0x0, recv_len+1);
    memcpy(tempbuf, (char *)recv_data, recv_len);
	
    LOG_PRINTF("%s[%d]: recv_len:%d, recv_data:%s\n", __FUNCTION__, __LINE__, recv_len, (char *)(tempbuf)); 
    uart_data.data = (UINT8 *)tempbuf;
    uart_data.len = recv_len;
    uart_data.port = 1;

    osa_status = OSAMsgQSend(uartMsgQ, sizeof(uartParam), (UINT8*)&uart_data, OSA_NO_SUSPEND);
    ASSERT(osa_status == OS_SUCCESS);
}


void uart4RecvCallback(UINT8 * recv_data, UINT32 recv_len)
{	
	uartParam uart_data = {0};
    OSA_STATUS osa_status;
    
    char *tempbuf = (char *)malloc(recv_len+1);
    memset(tempbuf, 0x0, recv_len+1);
    memcpy(tempbuf, (char *)recv_data, recv_len);
	
    LOG_PRINTF("%s[%d]: recv_len:%d, recv_data:%s\n", __FUNCTION__, __LINE__, recv_len, (char *)(tempbuf)); 
    uart_data.data = (UINT8 *)tempbuf;
    uart_data.len = recv_len;
    uart_data.port = 2;

    osa_status = OSAMsgQSend(uartMsgQ, sizeof(uartParam), (UINT8*)&uart_data, OSA_NO_SUSPEND);
    ASSERT(osa_status == OS_SUCCESS);
}


static void uart_thread(void *param)
{
    OSA_STATUS status;
    uartParam uart_data = {0};
	
    // uart uart3 uart4 默认波特率都是115200
    hal_UartOpenCb(UART_PORT_2, 9600, mainUartRecvCallback);

    //	HV9\HE9: uart3对应的有三组GPIO：2/3, 14/15, 53/54
    //	HV9V2: uart3对应的有四组GPIO：2/3, 10/11, 14/15, 53/54
    //

    hal_UartEnableGpio(UART_PORT_3, 10, 11);
    hal_UartOpenCb(UART_PORT_3, 9600, uart3RecvCallback);

    //	需要使用多组uart3的场景时,需要先disable掉之前uart对应的gpio
    //  hal_UartDisableGpio(UART_PORT_3, 10, 11);
    //  hal_UartEnableGpio(UART_PORT_3, 14, 15);
    //  hal_UartOpenCb(UART_PORT_3, 9600, uart3RecvCallback);

    hal_UartOpenCb(UART_PORT_4, 9600, uart4RecvCallback);
	
    while (1) {
        memset(&uart_data, 0x00, sizeof(uartParam));        
        status = OSAMsgQRecv(uartMsgQ, (UINT8 *)&uart_data, sizeof(uartParam), OSA_SUSPEND);    //recv data from uart
        if (status == OS_SUCCESS) {
            if (uart_data.data) {
                LOG_PRINTF("%s: port %d len:%d, data:%s\n", __FUNCTION__, uart_data.port, uart_data.len, (char *)(uart_data.data));
				
                if (uart_data.port == 0)
                    hal_UartWrite(UART_PORT_2, uart_data.data, uart_data.len);
				else if (uart_data.port == 1)
                    hal_UartWrite(UART_PORT_3, uart_data.data, uart_data.len);

				free(uart_data.data);
            }
        }
    }
}

int main(void)
{
    OSA_STATUS status;

    LOG_PRINTF("%s[%d]: starting...\n", __FUNCTION__, __LINE__);
    status = OSAMsgQCreate(&uartMsgQ, "uartMsgQ", sizeof(uartParam), 300, OS_FIFO);
    ASSERT(status == OS_SUCCESS);

    _task_stack = malloc(_TASK_STACK_SIZE);
    ASSERT(_task_stack != NULL);

    status = OSATaskCreate(&_task_ref, _task_stack, _TASK_STACK_SIZE, 82, "uart_thread", uart_thread, NULL);
    ASSERT(status == OS_SUCCESS);	

    return 0;
}